const { SceneryModel, HotelModel, RestaurantModel, PostModel } = require('../../models/index')
const { Op } = require('sequelize')

// 在景点、酒店、餐厅范围内搜索
const getSearchCategoryData = async (req, res) => {
  try {
    // 获取用户输入的搜索词
    const searchText = req.query.data

    // 搜索词为空的情况
    if (!searchText || searchText.trim() === '') {
      return res.status(200).json({
        title: '搜索词不能为空',
        data: []
      })
    }

    // 需要查询的模型数组集合
    let modelArray = [{ model: SceneryModel, type: 'scenery' }, { model: HotelModel, type: 'hotel' }, { model: RestaurantModel, type: 'restaurant' }]

    // 搜索匹配内容
    const searchPromises = modelArray.map(item => {
      // 构建 where 子句 
      const whereClause = [
        { name: { [Op.like]: `%${searchText}%` } },
        { address: { [Op.like]: `%${searchText}%` } },
        { rating: { [Op.eq]: Number(searchText) || null } },
        { type: { [Op.like]: `%${searchText}%` } }
      ]

      // 构建返回数组
      const attributesArray = [`${item.type}_id`, 'name', 'address', 'rating', 'type', 'price']

      if (item.type !== 'restaurant') {
        whereClause.push({ grade: { [Op.like]: `%${searchText}%` } })
        attributesArray.push('grade')
      }

      return item.model.findAll({
        where: {
          [Op.or]: whereClause
        },
        attributes: attributesArray
      }).then(result => {
        return result.map(item2 => ({
          ...item2.get({ plain: true }),
          dataType: item.type
        }))
      })
    })

    const searchResult = await Promise.all(searchPromises)
    const finalResult = searchResult.flat()

    if (finalResult.length === 0) {
      return res.status(200).json({
        title: '未找到匹配的搜索项',
        data: []
      })
    }

    // 返回查询结果
    return res.status(200).json({
      title: '景点/酒店/餐厅搜索结果',
      data: finalResult
    })

  } catch (error) {
    res.status(500).json({
      error: error.message
    })
  }
}

// 全局搜索
const getSearchAllData = async (req, res) => {
  try {
    // 获取用户输入的搜索词
    const searchText = req.query.data

    // 搜索词为空的情况
    if (!searchText || searchText.trim() === '') {
      return res.status(200).json({
        title: '搜索词不能为空',
        data: []
      })
    }

    // 需要查询的模型数组集合
    let modelArray = [
      { model: SceneryModel, type: 'scenery' },
      { model: HotelModel, type: 'hotel' },
      { model: RestaurantModel, type: 'restaurant' },
      { model: PostModel, type: 'post' }
    ]

    // 搜索匹配内容
    const searchPromises = modelArray.map(item => {
      // 构建 where 子句 
      let whereClause = [
        { name: { [Op.like]: `%${searchText}%` } },
        { address: { [Op.like]: `%${searchText}%` } },
        { rating: { [Op.eq]: Number(searchText) || null } },
        { type: { [Op.like]: `%${searchText}%` } }
      ]

      // 构建返回数组
      let attributesArray = [`${item.type}_id`, 'name', 'address', 'rating', 'type', 'price']

      if (item.type !== 'restaurant') {
        whereClause.push({ grade: { [Op.like]: `%${searchText}%` } })
        attributesArray.push('grade')
      }

      if (item.type === 'post') {
        whereClause = [
          { title: { [Op.like]: `%${searchText}%` } },
          { content: { [Op.like]: `%${searchText}%` } }
        ]
        attributesArray = ['post_id', 'user_id', 'title', 'association_id', 'type']
      }

      return item.model.findAll({
        where: {
          [Op.or]: whereClause
        },
        attributes: attributesArray
      }).then(result => {
        return result.map(item2 => ({
          ...item2.get({ plain: true }),
          dataType: item.type
        }))
      })
    })

    const searchResult = await Promise.all(searchPromises)
    const finalResult = searchResult.flat()

    if (finalResult.length === 0) {
      return res.status(200).json({
        title: '未找到匹配的搜索项',
        data: []
      })
    }

    // 返回查询结果
    return res.status(200).json({
      title: '全部搜索结果',
      data: finalResult
    })

  } catch (error) {
    res.status(500).json({
      error: error.message
    })
  }
}

module.exports = {
  getSearchCategoryData,
  getSearchAllData
}